package com.hxh.generater.vue.simple.gen;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.hxh.entity.Project;
import com.hxh.entity.ProjectTableFiledConfig;
import com.hxh.entity.ProjectTablePageConfig;
import com.hxh.entity.po.ClassInfo;
import com.hxh.entity.po.FieldName;
import com.hxh.generater.springBoot.GenerationTableInfo;
import com.hxh.generater.vue.ProcessFreemarkerTemplate;
import com.hxh.util.Common;
import com.hxh.util.GenUtil;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

/**
 * @ProjectName: AICode
 * @Package: com.hxh.generater
 * @Author: HXH
 * @Description: 生成view页面代码
 * @Date: 2023/11/28 15:08
 */
public class GenSimpleView {
    private static final String NOT_AUTO_CREATE_COMPONENT_TABLES = "use";

    /**
     * 生成view页面代码
     *
     * @param project                为空时，转为单页面，返回代码字符串形式，否则直接生成项目，返回null
     * @param classInfo              生成页面的类信息
     * @return
     * @throws Exception
     */
    public static String generationByFtlConfig(Project project, ClassInfo classInfo) throws Exception {
        boolean returnModel = false;
        if (project == null) {
            returnModel = true;
        }

        String className = classInfo.getClassName();
        String entityName = StringUtils.uncapitalize(classInfo.getClassName());
        String entityDesc = classInfo.getDesc();
        ProjectTablePageConfig projectTablePageConfig = classInfo.getProjectTablePageConfig();
        if (projectTablePageConfig == null) {
            //设置方便下面统一处理
            projectTablePageConfig = ProjectTablePageConfig.generationDefaultByClassInfo(classInfo);
        }

        StringBuilder searchConditionInput = new StringBuilder();
        StringBuilder elTableColumn = new StringBuilder();
        StringBuilder editFormInput = new StringBuilder();
        StringBuilder addFormInput = new StringBuilder();
        Map<String, String> defaultEntityMap = new HashMap<>();
        Map<String, String> queryKeysMap = new HashMap<>();

        Set<String> associationDialog = new HashSet<>();

        StringBuilder deleteIdList = new StringBuilder();

        String searchFields;
        String tableColumnFields;
        String addFields;
        String updateFields;

        searchFields = projectTablePageConfig.getSearchFields();
        tableColumnFields = projectTablePageConfig.getTableColumnFields();
        addFields = projectTablePageConfig.getAddFields();
        updateFields = projectTablePageConfig.getUpdateFields();

        List<String> searchFiledList = new ArrayList<>();
        List<String> tableColumnFieldList = new ArrayList<>();
        List<String> addFieldList = new ArrayList<>();
        List<String> updateFieldList = new ArrayList<>();

        //为了保持顺序
        Map<String, String> searchFiledMap = new HashMap<>();
        Map<String, String> tableColumnFieldMap = new HashMap<>();
        Map<String, String> addFieldMap = new HashMap<>();
        Map<String, String> updateFieldMap = new HashMap<>();

        if (StringUtils.isNotBlank(searchFields)) {
            searchFiledList = new ArrayList<>(Arrays.asList(searchFields.split(",")));
        }
        if (StringUtils.isNotBlank(tableColumnFields)) {
            tableColumnFieldList = new ArrayList<>(Arrays.asList(tableColumnFields.split(",")));
        }
        boolean showAddBtn = true;
        boolean showBatchImportBtn = true;
        boolean showBatchExportBtn = true;
        boolean showDeleteBtn = true;
        boolean showUpdateBtn = true;

        if (!"1".equals(projectTablePageConfig.getShowAdd())) {
            showAddBtn = false;
        }
        if (!"1".equals(projectTablePageConfig.getShowBatchAdd())) {
            showBatchImportBtn = false;
        }
        if (!"1".equals(projectTablePageConfig.getShowBatchExport())) {
            showBatchExportBtn = false;
        }
        if (!"1".equals(projectTablePageConfig.getShowDelete())) {
            showDeleteBtn = false;
        }
        if (!"1".equals(projectTablePageConfig.getShowUpdate())) {
            showUpdateBtn = false;
        }
        if (StringUtils.isNotBlank(addFields) && showAddBtn) {
            addFieldList = new ArrayList<>(Arrays.asList(addFields.split(",")));
        }
        if (StringUtils.isNotBlank(updateFields) && showUpdateBtn) {
            updateFieldList = new ArrayList<>(Arrays.asList(updateFields.split(",")));
        }

        Set<String> importSet = new HashSet<>();
        Map<String, String> otherReturnDataMap = new HashMap<>();

        StringBuilder additionMethod = new StringBuilder();
        boolean hasImageUpload = false;

        boolean hasFileManager = false;
        boolean hasAssociation = false;
        boolean hasCollection = false;
        Set<String> importComponents = new HashSet<>();

        StringBuilder formRule = new StringBuilder();
        Set<String> associationTableNameSet = new HashSet<>();
        for (FieldName fieldName : classInfo.getFieldNameList()) {
            String fieldJavaName = fieldName.getJavaName();
            ProjectTableFiledConfig projectTableFiledConfig = fieldName.getProjectTableFiledConfig();
            if (searchFiledList.contains(fieldName.getName())) {
                generationSearchConditionInput(searchFiledMap, fieldName, projectTableFiledConfig);

                if (projectTableFiledConfig != null && "checkbox".equals(projectTableFiledConfig.getShowType())) {
                    //多选框,是数组
                    queryKeysMap.put(fieldJavaName + "Arr", "undefined");
                }
                queryKeysMap.put(fieldJavaName, "undefined");
            }

            if (tableColumnFieldList.contains(fieldName.getName())) {
                generationTableColumn(tableColumnFieldMap, fieldName, projectTableFiledConfig);
            }

            if (addFieldList.contains(fieldName.getName())) {
                generationAddForm(addFieldMap, fieldName, projectTableFiledConfig);
            }

            if (updateFieldList.contains(fieldName.getName())) {
                generationEditForm(updateFieldMap, fieldName, projectTableFiledConfig);
            }
            String defaultValue = "undefined";
            if (StringUtils.isNotBlank(fieldName.getDefaultValue())) {
                defaultValue = "'" + fieldName.getDefaultValue() + "'";
            }
            defaultEntityMap.put(fieldJavaName, defaultValue);
            if (fieldName.isNotNull() && (addFieldList.contains(fieldName.getName()) || updateFieldList.contains(fieldName.getName()))) {
                String formRuleTips = "输入";
                String ruleFn = fieldJavaName;

                if (projectTableFiledConfig != null) {
                    if ("radio,checkbox,date,dateTime".contains(projectTableFiledConfig.getShowType())) {
                        formRuleTips = "选择";
                    }
                    formRuleTips += Common.getStringNotNull(projectTableFiledConfig.getShowName(), fieldName.getDesc());

                    if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                        ruleFn += "Arr";
                    }
                } else {
                    formRuleTips += fieldName.getDesc();
                }
//                 text, textarea, number, radio, checkbox, date,dateTime, file, img

                formRule.append("\n").append("          " + ruleFn + ": [{ required: true, message: \"请" + formRuleTips + "\" , trigger: 'blur'}],");
            }

            if (projectTableFiledConfig != null) {
                if ("img".equals(projectTableFiledConfig.getShowType())) {
                    hasImageUpload = true;
                } else if ("file".equals(projectTableFiledConfig.getShowType())) {
                    hasFileManager = true;
                } else if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                    //多选框,是数组
                    defaultEntityMap.put(fieldJavaName + "Arr", "undefined");
                } else if ("association".equals(projectTableFiledConfig.getShowType())) {
                    String associationTable = projectTableFiledConfig.getAssociationTable();
                    if (StringUtils.isBlank(associationTable)) {
                        throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为关联字段，但未配置关联表信息！");
                    }
                    JSONObject jsonObject = new JSONObject(associationTable);
                    String associationTableName = jsonObject.getStr("table");

                    if (!returnModel) {
                        generationComponentByConfig(project, associationTableName);
                    }

                    associationTableName = StrUtil.toCamelCase(associationTableName);
                    associationTableNameSet.add(associationTableName);
                    String upperAssociationTableName = StrUtil.upperFirst(associationTableName);

                    associationDialog.add("        <" + associationTableName + "-component :visible=\"" + associationTableName + "SelectVisible\" " +
                            " @close=\"" + associationTableName + "SelectVisible =false\" @onSelect=\"onComponentSelect\"></" + associationTableName + "-component>");

                    importSet.add("import " + upperAssociationTableName + "Component from \"@/views/" + associationTableName + "/component\";");
                    importComponents.add(upperAssociationTableName + "Component");
                    otherReturnDataMap.put(associationTableName + "SelectVisible", "false");

                    hasAssociation = true;
                } else if ("collection".equals(projectTableFiledConfig.getShowType())) {
                    String collectionTable = projectTableFiledConfig.getCollectionTable();
                    if (StringUtils.isBlank(collectionTable)) {
                        throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为一对多字段，但未配置关联表信息！");
                    }
                    JSONObject jsonObject = new JSONObject(collectionTable);
                    String collectionTableNameOri = jsonObject.getStr("table");
                    String collectionShowType = jsonObject.getStr("showType");
                    if ("vue".equals(collectionShowType)) {
                        String collectionTableName = StrUtil.toCamelCase(collectionTableNameOri);
                        String upperCollectionTableName = StrUtil.upperFirst(collectionTableName);

                        importComponents.add(upperCollectionTableName + "CollectionComponent");
                        importSet.add("import " + upperCollectionTableName + "CollectionComponent from \"@/views/" + collectionTableName + "/collectionComponent\";");
                        associationDialog.add("        <" + collectionTableName + "-collection-component :params=\"" + collectionTableName + "DialogParam\" :visible=\"" + collectionTableName + "DialogVisible\" @close=\"" + collectionTableName + "DialogVisible=false\"></" + collectionTableName + "-collection-component>");
                        otherReturnDataMap.put(collectionTableName + "DialogParam", "{}");
                        otherReturnDataMap.put(collectionTableName + "DialogParam", "{}");
                        otherReturnDataMap.put(collectionTableName + "DialogVisible", "false");

                        if (!returnModel) {
                            generationCollectionComponentByConfig(project, collectionTableNameOri);
                        }
                        hasCollection = true;
                    }
                }
            }
        }

        if (hasAssociation) {
            if (!CollectionUtils.isEmpty(associationTableNameSet)) {
                for (String s : associationTableNameSet) {
                    defaultEntityMap.put(s, "{}");
                    queryKeysMap.put(s, "{}");
                }
            }
        }

        for (String s : searchFiledList) {
            String v = searchFiledMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                searchConditionInput.append(v);
            }
        }
        StringBuilder elTableColumnExpandStr = new StringBuilder();
        for (String s : tableColumnFieldList) {
            String v = tableColumnFieldMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                elTableColumn.append(v);
            } else if (StringUtils.isNotBlank(tableColumnFieldMap.get(s + "List"))) {
                elTableColumn.append(tableColumnFieldMap.get(s + "List"));
            } else if (StringUtils.isNotBlank(tableColumnFieldMap.get(s + "__expand"))) {
                elTableColumnExpandStr.append(tableColumnFieldMap.get(s + "__expand"));
            }
        }
        for (String s : addFieldList) {
            String v = addFieldMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                addFormInput.append(v);
            }
        }
        for (String s : updateFieldList) {
            String v = updateFieldMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                editFormInput.append(v);
            }
        }
        for (FieldName fieldName : classInfo.getIdNameList()) {
            deleteIdList.append("'" + fieldName.getJavaName() + "': row." + fieldName.getJavaName() + ",");
        }
        if (deleteIdList.length() > 0) {
            deleteIdList.deleteCharAt(deleteIdList.length() - 1);
        }
        boolean showBatchAllMethod = false;

        if (showBatchImportBtn || showBatchExportBtn) {
            showBatchAllMethod = true;
            importComponents.add("BatchImportExport");
            importSet.add("import {${entityName!\"\"}PostRequireByConfig, ${entityName!\"\"}Download} from '@/api/${entityName!\"\"}';");
            if (showBatchExportBtn) {
                importSet.add("import BatchImportExport from \"@/views/component/batchImportExport\";");
            }
        }
        if (hasFileManager) {
            importComponents.add("FileManager");
            importSet.add("import FileManager from \"@/views/component/fileManager.vue\";");
        }
        if (hasImageUpload) {
            importSet.add("import {sysFilePostRequireByConfig} from '@/api/sysFile';");
            importSet.add("import {getBaseUri} from '@/utils/auth';");
        }
        importSet.add("import {${entityName!\"\"}PostRequire} from '@/api/${entityName!\"\"}';");

        try {
            //数据模型
            Map<String, Object> map = new HashMap<>();
            map.put("formRule", formRule.toString());
            map.put("searchConditionInput", searchConditionInput.toString());
            map.put("elTableColumn", elTableColumn.toString());
            map.put("editFormInput", editFormInput.toString());
            map.put("addFormInput", addFormInput.toString());
            map.put("queryKeysMap", queryKeysMap);
            map.put("defaultEntityMap", defaultEntityMap);
            map.put("deleteIdList", deleteIdList.toString());
            map.put("associationDialog", StringUtils.join(associationDialog, "\n"));
            map.put("showBatchAllMethod", showBatchAllMethod);
            map.put("importComponents", importComponents);
            map.put("importSet", importSet);
            map.put("otherReturnDataMap", otherReturnDataMap);
            map.put("additionMethod", additionMethod.toString());
            map.put("showDeleteBtn", showDeleteBtn);
            map.put("showUpdateBtn", showUpdateBtn);
            map.put("showBatchImportBtn", showBatchImportBtn);
            map.put("showAddBtn", showAddBtn);
            map.put("hasImageUpload", hasImageUpload);
            map.put("hasFileManager", hasFileManager);
            map.put("hasCollection", hasCollection);
            map.put("hasAssociation", hasAssociation);
            map.put("elTableColumnExpandStr", elTableColumnExpandStr.toString());
            map.put("className", className);
            map.put("entityName", entityName);
            map.put("entityDesc", entityDesc);
            map.put("showBatchExportBtn", showBatchExportBtn);

            String content = ProcessFreemarkerTemplate.processTemplateIntoString("simple/template/replace/view", "index", map);

            if (returnModel) {
                return content;
            }
            File file = GenUtil.newVueFile(project, "src\\views\\" + entityName + "\\", "index.vue");
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter writer = new BufferedWriter(fileWriter);
            writer.write(content);
            writer.close();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param project:   项目
     * @param tableName: 表名
     * @return void
     * @author HXH
     * @description: 生产collection一对多的组件
     * @date 2024/3/13
     **/
    private static void generationCollectionComponentByConfig(Project project, String tableName) throws Exception {
        if (NOT_AUTO_CREATE_COMPONENT_TABLES.equals(tableName)) {
            return;
        }
        ClassInfo classInfo = GenerationTableInfo.getTableInfo(project, null, tableName);
        GenSimpleApi.generationApi(project, classInfo);
        ProjectTablePageConfig projectTablePageConfig = classInfo.getProjectTablePageConfig();

        String className = classInfo.getClassName();
        String entityName = StringUtils.uncapitalize(classInfo.getClassName());

        String canAddResources = entityName + ":add";
        String canUpdateResources = entityName + ":update";
        String canDeleteResources = entityName + ":delete";

        String entityDesc = classInfo.getDesc();

        StringBuilder searchConditionInput = new StringBuilder();
        StringBuilder elTableColumn = new StringBuilder();
        StringBuilder editFormInput = new StringBuilder();
        StringBuilder addFormInput = new StringBuilder();
        Map<String, String> defaultEntityMap = new HashMap<>();
        Map<String, String> queryKeysMap = new HashMap<>();


        Set<String> associationDialog = new HashSet<>();

        StringBuilder deleteIdList = new StringBuilder();

        String searchFields;
        String tableColumnFields;
        String addFields;
        String updateFields;

        searchFields = projectTablePageConfig.getSearchFields();
        tableColumnFields = projectTablePageConfig.getTableColumnFields();
        addFields = projectTablePageConfig.getAddFields();
        updateFields = projectTablePageConfig.getUpdateFields();

        List<String> searchFiledList = new ArrayList<>();
        List<String> tableColumnFieldList = new ArrayList<>();
        List<String> addFieldList = new ArrayList<>();
        List<String> updateFieldList = new ArrayList<>();

        //为了保持顺序
        Map<String, String> searchFiledMap = new HashMap<>();
        Map<String, String> tableColumnFieldMap = new HashMap<>();
        Map<String, String> addFieldMap = new HashMap<>();
        Map<String, String> updateFieldMap = new HashMap<>();

        if (StringUtils.isNotBlank(searchFields)) {
            searchFiledList = new ArrayList<>(Arrays.asList(searchFields.split(",")));
        }
        if (StringUtils.isNotBlank(tableColumnFields)) {
            tableColumnFieldList = new ArrayList<>(Arrays.asList(tableColumnFields.split(",")));
        }

        boolean showAddBtn = true;
        boolean showDeleteBtn = true;
        boolean showUpdateBtn = true;

        String showAdd = projectTablePageConfig.getShowAdd();
        String showDelete = projectTablePageConfig.getShowDelete();
        String showUpdate = projectTablePageConfig.getShowUpdate();
        if (!"1".equals(showAdd)) {
            showAddBtn = false;
        }
        if (!"1".equals(showDelete)) {
            showDeleteBtn = false;
        }
        if (!"1".equals(showUpdate)) {
            showUpdateBtn = false;
        }
        if (StringUtils.isNotBlank(addFields) && showAddBtn) {
            addFieldList = new ArrayList<>(Arrays.asList(addFields.split(",")));
        }
        if (StringUtils.isNotBlank(updateFields) && showUpdateBtn) {
            updateFieldList = new ArrayList<>(Arrays.asList(updateFields.split(",")));
        }

        Set<String> importSet = new HashSet();
        Map<String, String> otherReturnDataMap = new HashMap<>();

        StringBuilder additionMethod = new StringBuilder();
        boolean hasImageUpload = false;

        boolean hasFileManager = false;
        boolean hasAssociation = false;
        Set<String> importComponents = new HashSet<>();

        StringBuilder formRule = new StringBuilder();
        Set<String> associationTableNameSet = new HashSet<>();
        for (FieldName fieldName : classInfo.getFieldNameList()) {
            String fieldJavaName = fieldName.getJavaName();
            ProjectTableFiledConfig projectTableFiledConfig = fieldName.getProjectTableFiledConfig();

            if (searchFiledList.contains(fieldName.getName())) {
                generationSearchConditionInput(searchFiledMap, fieldName, projectTableFiledConfig);

                if (projectTableFiledConfig != null && "checkbox".equals(projectTableFiledConfig.getShowType())) {
                    //多选框,是数组
                    queryKeysMap.put(fieldJavaName + "Arr", "undefined");
                }
                queryKeysMap.put(fieldJavaName, "undefined");
            }

            if (tableColumnFieldList.contains(fieldName.getName())) {
                generationTableColumn(tableColumnFieldMap, fieldName, projectTableFiledConfig);
            }

            if (addFieldList.contains(fieldName.getName())) {
                generationAddForm(addFieldMap, fieldName, projectTableFiledConfig);
            }

            if (updateFieldList.contains(fieldName.getName())) {
                generationEditForm(updateFieldMap, fieldName, projectTableFiledConfig);
            }
            String defaultValue = "undefined";
            if (StringUtils.isNotBlank(fieldName.getDefaultValue())) {
                defaultValue = "'" + fieldName.getDefaultValue() + "'";
            }

            defaultEntityMap.put(fieldJavaName, defaultValue);
            if (projectTableFiledConfig != null) {
                if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                    //多选框,是数组
                    defaultEntityMap.put(fieldJavaName + "Arr", "undefined");
                } else if ("association".equals(projectTableFiledConfig.getShowType())) {
                    String associationTable = projectTableFiledConfig.getAssociationTable();
                    if (StringUtils.isBlank(associationTable)) {
                        throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为关联字段，但未配置关联表信息！");
                    }
                    JSONObject jsonObject = new JSONObject(associationTable);
                    String table = jsonObject.getStr("table");
                    table = StrUtil.toCamelCase(table);
                    associationTableNameSet.add(table);
                }

            }

            if (fieldName.isNotNull() && (addFieldList.contains(fieldName.getName()) || updateFieldList.contains(fieldName.getName()))) {
                String formRuleTips = "输入";
                String ruleFn = fieldJavaName;

                if (projectTableFiledConfig != null) {
                    if ("radio,checkbox,date,dateTime".contains(projectTableFiledConfig.getShowType())) {
                        formRuleTips = "选择";
                    }
                    formRuleTips += Common.getStringNotNull(projectTableFiledConfig.getShowName(), fieldName.getDesc());

                    if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                        ruleFn += "Arr";
                    }
                } else {
                    formRuleTips += fieldName.getDesc();
                }
//                 text, textarea, number, radio, checkbox, date,dateTime, file, img

                formRule.append("\n").append("          " + ruleFn + ": [{ required: true, message: \"请" + formRuleTips + "\" , trigger: 'blur'}],");
            }

            if (projectTableFiledConfig != null) {
                if ("img".equals(projectTableFiledConfig.getShowType())) {
                    hasImageUpload = true;
                }
                if ("file".equals(projectTableFiledConfig.getShowType())) {
                    hasFileManager = true;
                }

                if ("association".equals(projectTableFiledConfig.getShowType())) {
                    String associationTable = projectTableFiledConfig.getAssociationTable();
                    if (StringUtils.isBlank(associationTable)) {
                        throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为关联字段，但未配置关联表信息！");
                    }
                    JSONObject jsonObject = new JSONObject(associationTable);
                    String associationTableName = jsonObject.getStr("table");

                    generationComponentByConfig(project, associationTableName);

                    associationTableName = StrUtil.toCamelCase(associationTableName);
                    String upperAssociationTableName = StrUtil.upperFirst(associationTableName);

                    associationDialog.add("    <" + associationTableName + "-component :visible=\"" + associationTableName + "SelectVisible\" " +
                            " @close=\"" + associationTableName + "SelectVisible =false\" @onSelect=\"onComponentSelect\"></" + associationTableName + "-component>");

                    importSet.add("  import " + upperAssociationTableName + "Component from \"@/views/" + associationTableName + "/component\";");
                    importComponents.add(upperAssociationTableName + "Component");
                    otherReturnDataMap.put(associationTableName + "SelectVisible", "false");
                    hasAssociation = true;
                } else if ("collection".equals(projectTableFiledConfig.getShowType())) {
                    //防止死循环，就不继续了
                }
            }
        }

        if (hasAssociation) {
            if (!CollectionUtils.isEmpty(associationTableNameSet)) {
                for (String s : associationTableNameSet) {
                    queryKeysMap.put(s, "{}");
                    defaultEntityMap.put(s, "{}");
                }
            }
        }

        for (String s : searchFiledList) {
            String v = searchFiledMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                searchConditionInput.append(v);
            }
        }
        StringBuilder elTableColumnExpandStr = new StringBuilder();
        for (String s : tableColumnFieldList) {
            String v = tableColumnFieldMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                elTableColumn.append(v);
            } else if (StringUtils.isNotBlank(tableColumnFieldMap.get(s + "List"))) {
                elTableColumn.append(tableColumnFieldMap.get(s + "List"));
            } else if (StringUtils.isNotBlank(tableColumnFieldMap.get(s + "__expand"))) {
                elTableColumnExpandStr.append(tableColumnFieldMap.get(s + "__expand"));
            }
        }
        for (String s : addFieldList) {
            String v = addFieldMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                addFormInput.append(v);
            }
        }

        for (String s : updateFieldList) {
            String v = updateFieldMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                editFormInput.append(v);
            }
        }
        for (FieldName fieldName : classInfo.getIdNameList()) {
            deleteIdList.append("'" + fieldName.getJavaName() + "': row." + fieldName.getJavaName() + ",");
        }
        if (deleteIdList.length() > 0) {
            deleteIdList.deleteCharAt(deleteIdList.length() - 1);
        }

        if (hasFileManager) {
            importComponents.add("FileManager");
            importSet.add("import FileManager from \"@/views/component/fileManager.vue\";");
        }
        if (hasImageUpload) {
            importSet.add("import {sysFilePostRequireByConfig} from '@/api/sysFile';");
            importSet.add("import {getBaseUri} from '@/utils/auth';");
        }
        importSet.add("import {${entityName!\"\"}PostRequire} from '@/api/${entityName!\"\"}';");
        importSet.add("import store from '@/store';");

        try {
            Map<String, Object> map = new HashMap<>();
            map.put("formRule", formRule.toString());
            map.put("searchConditionInput", searchConditionInput.toString());
            map.put("elTableColumn", elTableColumn.toString());
            map.put("editFormInput", editFormInput.toString());
            map.put("addFormInput", addFormInput.toString());
            map.put("queryKeysMap", queryKeysMap);
            map.put("defaultEntityMap", defaultEntityMap);
            map.put("deleteIdList", deleteIdList.toString());
            map.put("associationDialog", StringUtils.join(associationDialog, "\n"));
            map.put("importComponents", importComponents);
            map.put("importSet", importSet);
            map.put("otherReturnDataMap", otherReturnDataMap);
            map.put("additionMethod", additionMethod.toString());
            map.put("showDeleteBtn", showDeleteBtn);
            map.put("showUpdateBtn", showUpdateBtn);
            map.put("showAddBtn", showAddBtn);
            map.put("hasImageUpload", hasImageUpload);
            map.put("hasFileManager", hasFileManager);
            map.put("hasAssociation", hasAssociation);
            map.put("elTableColumnExpandStr", elTableColumnExpandStr.toString());
            map.put("className", className);
            map.put("entityName", entityName);
            map.put("entityDesc", entityDesc);
            map.put("canDeleteResources", canDeleteResources);
            map.put("canUpdateResources", canUpdateResources);
            map.put("canAddResources", canAddResources);

            String content = ProcessFreemarkerTemplate.processTemplateIntoString("simple/template/replace/view", "collectionComponent", map);
            File file = GenUtil.newVueFile(project, "src\\views\\" + entityName + "\\", "collectionComponent.vue");
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter writer = new BufferedWriter(fileWriter);
            writer.write(content);
            writer.close();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param project:   项目
     * @param tableName: 表名
     * @return void
     * @author HXH
     * @description: 生产component一对一的组件
     * @date 2024/3/13
     **/
    private static void generationComponentByConfig(Project project, String tableName) throws Exception {
        if ("user".equals(tableName)) {
            return;
        }
        ClassInfo classInfo = GenerationTableInfo.getTableInfo(project, null, tableName);
        GenSimpleApi.generationApi(project, classInfo);
        ProjectTablePageConfig projectTablePageConfig = classInfo.getProjectTablePageConfig();

        String className = classInfo.getClassName();
        String entityName = StringUtils.uncapitalize(classInfo.getClassName());
        String entityDesc = classInfo.getDesc();

        if (projectTablePageConfig == null) {
            //设置方便下面统一处理
            projectTablePageConfig = ProjectTablePageConfig.generationDefaultByClassInfo(classInfo);
        }

        StringBuilder searchConditionInput = new StringBuilder();
        StringBuilder elTableColumn = new StringBuilder();
        Map<String, String> defaultEntityMap = new HashMap<>();
        Map<String, String> queryKeysMap = new HashMap<>();

        Set<String> associationDialog = new HashSet<>();

        String searchFields;
        String tableColumnFields;

        searchFields = projectTablePageConfig.getSearchFields();
        tableColumnFields = projectTablePageConfig.getTableColumnFields();

        List<String> searchFiledList = new ArrayList<>();
        List<String> tableColumnFieldList = new ArrayList<>();

        //为了保持顺序
        Map<String, String> searchFiledMap = new HashMap<>();
        Map<String, String> tableColumnFieldMap = new HashMap<>();

        if (StringUtils.isNotBlank(searchFields)) {
            searchFiledList = new ArrayList<>(Arrays.asList(searchFields.split(",")));
        }
        if (StringUtils.isNotBlank(tableColumnFields)) {
            tableColumnFieldList = new ArrayList<>(Arrays.asList(tableColumnFields.split(",")));
        }

        Set<String> importSet = new HashSet<>();
        Map<String, String> otherReturnDataMap = new HashMap<>();

        StringBuilder additionMethod = new StringBuilder();
        boolean hasImageUpload = false;
        boolean hasAssociation = false;
        boolean hasFileManager = false;
        Set<String> importComponents = new HashSet<>();
        Set<String> associationTableNameSet = new HashSet<>();
        for (FieldName fieldName : classInfo.getFieldNameList()) {
            ProjectTableFiledConfig projectTableFiledConfig = fieldName.getProjectTableFiledConfig();
            if (searchFiledList.contains(fieldName.getName())) {
                generationSearchConditionInput(searchFiledMap, fieldName, projectTableFiledConfig);

                if (projectTableFiledConfig != null && "checkbox".equals(projectTableFiledConfig.getShowType())) {
                    //多选框,是数组
                    queryKeysMap.put(fieldName.getJavaName() + "Arr", "undefined");
                }
                queryKeysMap.put(fieldName.getJavaName(), "undefined");
            }

            if (tableColumnFieldList.contains(fieldName.getName())) {
                generationTableColumn(tableColumnFieldMap, fieldName, projectTableFiledConfig);
            }
            if (projectTableFiledConfig != null) {
                if ("img".equals(projectTableFiledConfig.getShowType())) {
                    hasImageUpload = true;
                }
                if ("file".equals(projectTableFiledConfig.getShowType())) {
                    hasFileManager = true;
                }
                if ("association".equals(projectTableFiledConfig.getShowType())) {
                    String associationTable = projectTableFiledConfig.getAssociationTable();
                    if (StringUtils.isBlank(associationTable)) {
                        throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为关联字段，但未配置关联表信息！");
                    }
                    JSONObject jsonObject = new JSONObject(associationTable);
                    String associationTableName = jsonObject.getStr("table");

                    associationTableName = StrUtil.toCamelCase(associationTableName);
                    associationTableNameSet.add(associationTableName);
                    String upperAssociationTableName = StrUtil.upperFirst(associationTableName);

                    associationDialog.add("        <" + associationTableName + "-component :visible=\"" + associationTableName + "SelectVisible\" " +
                            " @close=\"" + associationTableName + "SelectVisible =false\" @onSelect=\"onComponentSelect\"></" + associationTableName + "-component>");

                    importSet.add("import " + upperAssociationTableName + "Component from \"@/views/" + associationTableName + "/component\";");
                    importComponents.add(upperAssociationTableName + "Component");
                    otherReturnDataMap.put(associationTableName + "SelectVisible", "false");

                    hasAssociation = true;
                }
            }
        }
        if (hasAssociation) {
            if (!CollectionUtils.isEmpty(associationTableNameSet)) {
                for (String s : associationTableNameSet) {
                    defaultEntityMap.put(s, "{}");
                    queryKeysMap.put(s, "{}");
                }
            }
        }
        for (String s : searchFiledList) {
            String v = searchFiledMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                searchConditionInput.append(v);
            }
        }
        StringBuilder elTableColumnExpandStr = new StringBuilder();
        for (String s : tableColumnFieldList) {
            String v = tableColumnFieldMap.get(s);
            if (StringUtils.isNotBlank(v)) {
                elTableColumn.append(v);
            } else if (StringUtils.isNotBlank(tableColumnFieldMap.get(s + "List"))) {
                elTableColumn.append(tableColumnFieldMap.get(s + "List"));
            } else if (StringUtils.isNotBlank(tableColumnFieldMap.get(s + "__expand"))) {
                elTableColumnExpandStr.append(tableColumnFieldMap.get(s + "__expand"));
            }
        }
        importSet.add("import {${entityName!\"\"}PostRequire} from '@/api/${entityName!\"\"}';");
        if (hasFileManager) {
            importComponents.add("FileManager");
            importSet.add("import FileManager from \"@/views/component/fileManager.vue\";");
        }
        if (hasImageUpload) {
            importSet.add("import {sysFilePostRequireByConfig} from '@/api/sysFile';");
            importSet.add("import {getBaseUri} from '@/utils/auth';");
        }
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("searchConditionInput", searchConditionInput.toString());
            map.put("elTableColumn", elTableColumn.toString());
            map.put("queryKeysMap", queryKeysMap);
            map.put("associationDialog", StringUtils.join(associationDialog, "\n"));
            map.put("defaultEntityMap", defaultEntityMap);
            map.put("importComponents", importComponents);
            map.put("importSet", importSet);
            map.put("otherReturnDataMap", otherReturnDataMap);
            map.put("additionMethod", additionMethod.toString());
            map.put("hasImageUpload", hasImageUpload);
            map.put("hasFileManager", hasFileManager);
            map.put("elTableColumnExpandStr", elTableColumnExpandStr.toString());
            map.put("className", className);
            map.put("entityName", entityName);
            map.put("entityDesc", entityDesc);
            map.put("hasAssociation", hasAssociation);

            String content = ProcessFreemarkerTemplate.processTemplateIntoString("simple/template/replace/view", "component", map);
            File file = GenUtil.newVueFile(project, "src\\views\\" + entityName + "\\", "component.vue");
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter writer = new BufferedWriter(fileWriter);
            writer.write(content);
            writer.close();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成搜索框的代码
     *
     * @param searchFiledMap
     * @param fieldName
     * @param projectTableFiledConfig
     * @throws IOException
     * @throws TemplateException
     */
    private static void generationSearchConditionInput(Map<String, String> searchFiledMap, FieldName fieldName, ProjectTableFiledConfig projectTableFiledConfig) throws IOException, TemplateException {
        StringBuilder searchConditionInput = new StringBuilder();

        Map<String, Object> searchConditionMap = new HashMap<>();
        searchConditionMap.put("vmodel", "listQuery." + fieldName.getJavaName());
        String contentStr = "";
        String label;
        if (projectTableFiledConfig == null) {
            label = Common.getStringNotNull(fieldName.getDesc(), fieldName.getJavaName());
            searchConditionMap.put("label", label);
            contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                    "input", searchConditionMap);
        } else {
            label = Common.getStringNotNull(projectTableFiledConfig.getShowName(), fieldName.getDesc());
            searchConditionMap.put("label", label);

//            类型: text, textarea, number, radio, checkbox, date,dateTime, file, img
            if ("text".equals(projectTableFiledConfig.getShowType()) || "textarea".equals(projectTableFiledConfig.getShowType())) {//文本框
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "input", searchConditionMap);
            } else if ("number".equals(projectTableFiledConfig.getShowType())) {
                searchConditionMap.put("type", "number");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "input", searchConditionMap);
            } else if ("date".equals(projectTableFiledConfig.getShowType())) {
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "datePicker", searchConditionMap);
            } else if ("dateTime".equals(projectTableFiledConfig.getShowType())) {
                searchConditionMap.put("valueFormat", "yyyy-MM-dd HH:mm:ss");
                searchConditionMap.put("type", "datetime");
                searchConditionMap.put("placeholder", "请选择日期时间");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "datePicker", searchConditionMap);
            } else if ("radio".equals(projectTableFiledConfig.getShowType())) {
                String showSelectOption = projectTableFiledConfig.getShowSelectOption();
                if (StringUtils.isBlank(showSelectOption)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为单选框，但未配置选项值！");
                }
                JSONObject jsonObject = new JSONObject(showSelectOption);
                searchConditionMap.put("optionData", jsonObject);
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate("select", searchConditionMap);
            } else if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                String showSelectOption = projectTableFiledConfig.getShowSelectOption();
                if (StringUtils.isBlank(showSelectOption)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置多选框，但未配置选项值！");
                }
                JSONObject jsonObject = new JSONObject(showSelectOption);
                searchConditionMap.put("optionData", jsonObject);
                searchConditionMap.put("multiple", "true");
                searchConditionMap.put("vmodel", "listQuery." + fieldName.getJavaName() + "Arr");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate("select", searchConditionMap);
            } else if ("association".equals(projectTableFiledConfig.getShowType())) {
                String associationTable = projectTableFiledConfig.getAssociationTable();
                if (StringUtils.isBlank(associationTable)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为关联字段，但未配置关联表信息！");
                }
                JSONObject jsonObject = new JSONObject(associationTable);
                String tableName = jsonObject.getStr("table");
                String associationField = jsonObject.getStr("associationField");
                tableName = StrUtil.toCamelCase(tableName);
                associationField = StrUtil.toCamelCase(associationField);
                if (jsonObject.getStr("showField") != null) {
                    String showField = jsonObject.getStr("showField");
                    showField = StrUtil.toCamelCase(showField);

                    searchConditionMap.put("vif", "listQuery." + tableName + "." + showField);
                    searchConditionMap.put("style", "color: grey");
                    searchConditionMap.put("content", "已选择: {{listQuery." + tableName + "." + showField + "}}");
                    contentStr = ProcessFreemarkerTemplate.processElementUITemplate("span", searchConditionMap);

                    searchConditionMap.remove("vif");
                    searchConditionMap.put("style", "margin-left: 10px");
                    searchConditionMap.put("label", "选择" + label);
                    searchConditionMap.put("click", "showComponent(true,'" + fieldName.getJavaName() + "','" + tableName + "','" + associationField + "','" + showField + "')");
                    contentStr += ProcessFreemarkerTemplate.processElementUITemplate("button", searchConditionMap);
                }
            }
        }
        searchConditionInput.append(generationFormItem(label, contentStr, fieldName.getJavaName()));
        searchFiledMap.put(fieldName.getName(), searchConditionInput.toString());
    }

    /**
     * 生成table展示列的代码
     *
     * @param tableColumnFieldMap
     * @param fieldName
     * @param projectTableFiledConfig
     * @throws IOException
     * @throws TemplateException
     */
    private static void generationTableColumn(Map<String, String> tableColumnFieldMap, FieldName fieldName, ProjectTableFiledConfig projectTableFiledConfig) throws IOException, TemplateException {
        StringBuilder elTableColumn = new StringBuilder();
        Map<String, String> tableColumnMap = new HashMap<>();
        tableColumnMap.put("prop", fieldName.getJavaName());
        if (projectTableFiledConfig == null) {
            tableColumnMap.put("label", Common.getStringNotNull(fieldName.getDesc(), fieldName.getJavaName()));
            String showInExpandStr = ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap);
            elTableColumn.append(showInExpandStr);
        } else {
            String label = Common.getStringNotNull(projectTableFiledConfig.getShowName(), fieldName.getDesc());
            tableColumnMap.put("label", label);

            boolean showInExpand = "1".equals(projectTableFiledConfig.getShowInExpand());
            StringBuilder showInExpandStr = new StringBuilder();
//            类型: text, textarea, number, radio, checkbox, date,dateTime, file, img
            if ("text".equals(projectTableFiledConfig.getShowType()) || "number".equals(projectTableFiledConfig.getShowType()) ||
                    "date".equals(projectTableFiledConfig.getShowType()) || "dateTime".equals(projectTableFiledConfig.getShowType())) {
                if (showInExpand) {
                    showInExpandStr = new StringBuilder("              <el-form-item label=\"" + label + ": \">\n" +
                            "                <div style=\"white-space: pre-wrap;\">{{ scope.row." + fieldName.getJavaName() + " }}</div>\n" +
                            "              </el-form-item>\n");
                    tableColumnFieldMap.put(fieldName.getName() + "__expand", showInExpandStr.toString());
                    return;
                }

                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap));
                elTableColumn.append(showInExpandStr);
            } else if ("textarea".equals(projectTableFiledConfig.getShowType())) {
                if (showInExpand) {
                    showInExpandStr = new StringBuilder("              <el-form-item label=\"" + label + ": \">\n" +
                            "                <div style=\"white-space: pre-wrap;\">{{ scope.row." + fieldName.getJavaName() + " }}</div>\n" +
                            "              </el-form-item>\n");
                    tableColumnFieldMap.put(fieldName.getName() + "__expand", showInExpandStr.toString());
                    return;
                }

                tableColumnMap.put("content", "<div style=\"white-space: pre-line;text-align: left\">{{scope.row." + fieldName.getJavaName() + "}}</div>\n");
                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap));
                elTableColumn.append(showInExpandStr);
            } else if ("radio".equals(projectTableFiledConfig.getShowType())) {
                String showSelectOption = projectTableFiledConfig.getShowSelectOption();
                if (StringUtils.isBlank(showSelectOption)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为单选框，但未配置选项值！");
                }
                JSONObject jsonObject = new JSONObject(showSelectOption);
                //以tag形式展示：0否 1是
                boolean asTag = "1".equals(projectTableFiledConfig.getShowAsTag());
                List<Map<String, Object>> listData = new ArrayList<>();
                Map<String, Object> data;
                if (asTag) {
                    String tagColorOption = projectTableFiledConfig.getShowTagColor();
                    JSONObject tagColorJson = new JSONObject(tagColorOption);
                    for (String s : jsonObject.keySet()) {
                        data = new HashMap<>();
                        String color = Common.getStringNotNull(tagColorJson.getStr(s), "primary");
                        data.put("type", color);
                        data.put("tagName", jsonObject.getStr(s));
                        data.put("vif", "scope.row." + fieldName.getJavaName() + " == '" + s + "'");
                        listData.add(data);
                    }
                } else {
                    for (String s : jsonObject.keySet()) {
                        data = new HashMap<>();
                        data.put("content", jsonObject.getStr(s));
                        data.put("vif", "scope.row." + fieldName.getJavaName() + " == '" + s + "'");
                        listData.add(data);
                    }
                }
                data = new HashMap<>();
                data.put("listData", listData);
                showInExpandStr.append(ProcessFreemarkerTemplate.processElementUITemplate(asTag ? "tag" : "span", data));

                if (showInExpand) {
                    showInExpandStr = new StringBuilder(generationFormItem(label, showInExpandStr.toString(), fieldName.getJavaName()));
                    tableColumnFieldMap.put(fieldName.getName() + "__expand", showInExpandStr.toString());
                    return;
                }

                tableColumnMap.put("content", showInExpandStr.toString());
                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap));
                elTableColumn.append(showInExpandStr);

            } else if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                String showSelectOption = projectTableFiledConfig.getShowSelectOption();
                if (StringUtils.isBlank(showSelectOption)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为多选框，但未配置选项值！");
                }

                JSONObject jsonObject = new JSONObject(showSelectOption);
                //以tag形式展示：0否 1是
                boolean asTag = "1".equals(projectTableFiledConfig.getShowAsTag());
                List<Map<String, Object>> listData = new ArrayList<>();
                Map<String, Object> data;
                if (asTag) {
                    String tagColorOption = projectTableFiledConfig.getShowTagColor();
                    JSONObject tagColorJson = new JSONObject(tagColorOption);
                    for (String s : jsonObject.keySet()) {
                        data = new HashMap<>();
                        String color = Common.getStringNotNull(tagColorJson.getStr(s), "primary");
                        data.put("type", color);
                        data.put("tagName", jsonObject.getStr(s));
                        data.put("vif", "scope.row." + fieldName.getJavaName() + " && scope.row." + fieldName.getJavaName() + ".split(',').indexOf('" + s + "') !== -1");
                        listData.add(data);
                    }
                } else {
                    for (String s : jsonObject.keySet()) {
                        data = new HashMap<>();
                        data.put("content", jsonObject.getStr(s));
                        data.put("vif", "scope.row." + fieldName.getJavaName() + " && scope.row." + fieldName.getJavaName() + ".split(',').indexOf('" + s + "') !== -1");
                        listData.add(data);
                    }
                }
                data = new HashMap<>();
                data.put("listData", listData);
                showInExpandStr.append(ProcessFreemarkerTemplate.processElementUITemplate(asTag ? "tag" : "span", data));

                if (showInExpand) {
                    showInExpandStr = new StringBuilder(generationFormItem(label, showInExpandStr.toString(), fieldName.getJavaName()));
                    tableColumnFieldMap.put(fieldName.getName() + "__expand", showInExpandStr.toString());
                    return;
                }

                tableColumnMap.put("content", showInExpandStr.toString());
                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap));
                elTableColumn.append(showInExpandStr);
            } else if ("img".equals(projectTableFiledConfig.getShowType())) {
                Map<String, String> data = new HashMap<>();
                data.put("vif", "scope.row." + fieldName.getJavaName());
                data.put("src", "(baseUri + downloadPersonalFileUrl + scope.row." + fieldName.getJavaName() + ")");
                data.put("previewSrcList", "[(baseUri + downloadPersonalFileUrl + scope.row." + fieldName.getJavaName() + ")]");

                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate(projectTableFiledConfig.getShowType(), data)).append("\n");
                if (showInExpand) {
                    showInExpandStr = new StringBuilder(generationFormItem(label, showInExpandStr.toString(), fieldName.getJavaName()));
                    tableColumnFieldMap.put(fieldName.getName() + "__expand", showInExpandStr.toString());
                    return;
                }

                tableColumnMap.put("content", showInExpandStr.toString());
                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap));
                elTableColumn.append(showInExpandStr);
            } else if ("file".equals(projectTableFiledConfig.getShowType())) {

                Map<String, String> data = new HashMap<>();
                data.put("click", "handleManagerFile(scope.row,'" + fieldName.getJavaName() + "')");
                data.put("label", "文件详情");
                showInExpandStr = new StringBuilder("            " + ProcessFreemarkerTemplate.processElementUITemplate("button", data));
                if (showInExpand) {
                    showInExpandStr = new StringBuilder(generationFormItem(label, showInExpandStr.toString(), fieldName.getJavaName()));
                    tableColumnFieldMap.put(fieldName.getName() + "__expand", showInExpandStr.toString());
                    return;
                }

                tableColumnMap.put("content", showInExpandStr.toString());
                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap));
                elTableColumn.append(showInExpandStr).append("\n");
            } else if ("rate".equals(projectTableFiledConfig.getShowType())) {
                Map<String, String> data = new HashMap<>();
                data.put("vmodel", "scope.row." + fieldName.getJavaName());
                data.put("disabled", "");
                data.put("showScore", "");
                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("rate", data)).append("\n");

                if (showInExpand) {
                    showInExpandStr = new StringBuilder(generationFormItem(label, showInExpandStr.toString(), fieldName.getJavaName()));
                    tableColumnFieldMap.put(fieldName.getName() + "__expand", showInExpandStr.toString());
                    return;
                }
                tableColumnMap.put("content", showInExpandStr.toString());
                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap)).append("\n");
                elTableColumn.append(showInExpandStr);

            } else if ("association".equals(projectTableFiledConfig.getShowType())) {
                String associationTable = projectTableFiledConfig.getAssociationTable();
                if (StringUtils.isBlank(associationTable)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为关联字段，但未配置关联表信息！");
                }
                JSONObject jsonObject = new JSONObject(associationTable);
                String showFieldStr = "scope.row." + fieldName.getJavaName();
                if (jsonObject.getStr("showField") != null) {
                    String tableName = jsonObject.getStr("table");
                    String showField = jsonObject.getStr("showField");
                    tableName = StrUtil.toCamelCase(tableName);
                    showField = StrUtil.toCamelCase(showField);
                    showFieldStr = "(scope.row." + tableName + " || {})." + showField;
                }
                showInExpandStr = new StringBuilder("             {{" + showFieldStr + "}}\n");
                if (showInExpand) {
                    showInExpandStr = new StringBuilder(generationFormItem(label, showInExpandStr.toString(), fieldName.getJavaName()));
                    tableColumnFieldMap.put(fieldName.getName() + "__expand", showInExpandStr.toString());
                    return;
                }
                tableColumnMap.put("content", showInExpandStr.toString());
                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap));
                elTableColumn.append(showInExpandStr).append("\n");
            } else if ("collection".equals(projectTableFiledConfig.getShowType())) {
                String collectionTable = projectTableFiledConfig.getCollectionTable();
                if (StringUtils.isBlank(collectionTable)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为关联字段，但未配置关联表信息！");
                }
                JSONObject jsonObject = new JSONObject(collectionTable);
                String collectionShowType = jsonObject.getStr("showType");
                if (!"vue".equals(collectionShowType)) {
                    return;
                }
                String showFieldStr = "scope.row." + fieldName.getJavaName();
//                {"table":"comments","associationField":"file_id","showType":"data"}

                String tableName = jsonObject.getStr("table");
                String associationField = jsonObject.getStr("associationField");
                tableName = StrUtil.toCamelCase(tableName);
                associationField = StrUtil.toCamelCase(associationField);

                Map<String, String> data = new HashMap<>();
                data.put("click", "handleManagerCollectionComponent('" + tableName + "','" + associationField + "'," + showFieldStr + ")");
                data.put("label", label + "详情");
                showInExpandStr = new StringBuilder("            " + ProcessFreemarkerTemplate.processElementUITemplate("button", data));

                if (showInExpand) {
                    showInExpandStr = new StringBuilder(generationFormItem(label, showInExpandStr.toString(), fieldName.getJavaName()));
                    tableColumnFieldMap.put(fieldName.getName() + "__expand", showInExpandStr.toString());
                    return;
                }

                tableColumnMap.put("content", showInExpandStr.toString());
                showInExpandStr = new StringBuilder(ProcessFreemarkerTemplate.processElementUITemplate("tableColumn", tableColumnMap));
                elTableColumn.append(showInExpandStr);
            }

        }
        String oldStr = tableColumnFieldMap.get(fieldName.getName());
        String oldStrList = tableColumnFieldMap.get(fieldName.getName() + "List");
        if (StringUtils.isBlank(oldStr) && StringUtils.isBlank(oldStrList)) {
            tableColumnFieldMap.put(fieldName.getName(), elTableColumn.toString());
        } else {
            if (StringUtils.isNotBlank(oldStrList)) {
                oldStr = oldStrList + elTableColumn.toString();
                tableColumnFieldMap.put(fieldName.getName() + "List", oldStr);
            } else {
                oldStr = oldStr + elTableColumn.toString();
                tableColumnFieldMap.put(fieldName.getName() + "List", oldStr);
                tableColumnFieldMap.remove(fieldName.getName());
            }
        }
    }

    /**
     * 生成编辑框的代码
     *
     * @param updateFieldMap
     * @param fieldName
     * @param projectTableFiledConfig
     * @throws IOException
     * @throws TemplateException
     */
    private static void generationEditForm(Map<String, String> updateFieldMap, FieldName fieldName,
                                           ProjectTableFiledConfig projectTableFiledConfig) throws IOException, TemplateException {
        if (fieldName.isAutIncrement()) {
            //自增的字段就不需要手动填写了
            return;
        }
        StringBuilder editFormStr = new StringBuilder();
        Map<String, Object> editConditionMap = new HashMap<>();
        editConditionMap.put("vmodel", "${entityName!\"\"}." + fieldName.getJavaName());
        if (fieldName.isNotNull()) {
            editConditionMap.put("clearable", "false");
        }
        if (fieldName.getMaxLength() > 0) {
            editConditionMap.put("maxlength", fieldName.getMaxLength());
            editConditionMap.put("showWordLimit", "true");
        }
        if (fieldName.isNotNull()) {
            editConditionMap.put("prop", fieldName.getJavaName());
        }
        String contentStr = "";
        String label;

        if (projectTableFiledConfig == null) {
            label = Common.getStringNotNull(fieldName.getDesc(), fieldName.getJavaName());
            editConditionMap.put("label", label);
            contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                    "input", editConditionMap);
        } else {
            label = Common.getStringNotNull(projectTableFiledConfig.getShowName(), fieldName.getDesc());
            editConditionMap.put("label", label);

            if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                editConditionMap.put("prop", fieldName.getJavaName() + "Arr");
            }
//            类型: text, textarea, number, radio, checkbox, date,dateTime, file, img
            if ("text".equals(projectTableFiledConfig.getShowType())) {//文本框
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "input", editConditionMap);
            } else if ("textarea".equals(projectTableFiledConfig.getShowType())) {//文本框
                editConditionMap.put("type", "textarea");
                editConditionMap.put("autosize", "true");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "input", editConditionMap);
            } else if ("number".equals(projectTableFiledConfig.getShowType())) {
                editConditionMap.put("type", "number");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "input", editConditionMap);
            } else if ("date".equals(projectTableFiledConfig.getShowType())) {
                editConditionMap.put("style", "width: 100%;");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "datePicker", editConditionMap);
            } else if ("dateTime".equals(projectTableFiledConfig.getShowType())) {
                editConditionMap.put("style", "width: 100%;");
                editConditionMap.put("placeholder", "选择日期时间");
                editConditionMap.put("type", "datetime");
                editConditionMap.put("valueFormat", "yyyy-MM-dd HH:mm:ss");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "datePicker", editConditionMap);
            } else if ("radio".equals(projectTableFiledConfig.getShowType())) {//单选
                String showSelectOption = projectTableFiledConfig.getShowSelectOption();
                if (StringUtils.isBlank(showSelectOption)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为单选框，但未配置选项值！");
                }
                JSONObject jsonObject = new JSONObject(showSelectOption);
                editConditionMap.put("optionData", jsonObject);
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate("select", editConditionMap);
            } else if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                String showSelectOption = projectTableFiledConfig.getShowSelectOption();
                if (StringUtils.isBlank(showSelectOption)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置多选框，但未配置选项值！");
                }
                JSONObject jsonObject = new JSONObject(showSelectOption);
                editConditionMap.put("optionData", jsonObject);
                editConditionMap.put("multiple", "true");
                editConditionMap.put("vmodel", "${entityName!\"\"}." + fieldName.getJavaName() + "Arr");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate("select", editConditionMap);
            } else if ("img".equals(projectTableFiledConfig.getShowType())) {
                editConditionMap.put("accept", "'.png, .jpg, .jpeg'");
                editConditionMap.put("listType", "picture");
                editConditionMap.put("fileList", "${entityName!\"\"}." + fieldName.getJavaName() + "?[{url:(baseUri + downloadPersonalFileUrl+${entityName!\"\"}." + fieldName.getJavaName() + ")}]:[]");
                editConditionMap.put("onRemove", "()=>handleRemoveImage('" + fieldName.getJavaName() + "')");
                editConditionMap.put("onExceed", "handleImageExceed");
                editConditionMap.put("beforeUpload", "beforeImageUpload");
                editConditionMap.put("httpRequest", "(file)=>handleImageUpload(file,'" + fieldName.getJavaName() + "')");
                editConditionMap.put("uploadTip", "只能上传jpg/png/jpeg文件，且不超过2MB");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate("upload", editConditionMap);
            } else if ("file".equals(projectTableFiledConfig.getShowType())) {
                editConditionMap.put("label", "文件管理");
                editConditionMap.put("click", "handleManagerFile(${entityName!\"\"},'" + fieldName.getJavaName() + "')");
                contentStr += ProcessFreemarkerTemplate.processElementUITemplate("button", editConditionMap);
            } else if ("rate".equals(projectTableFiledConfig.getShowType())) {
                editConditionMap.put("showScore", "true");
                contentStr += ProcessFreemarkerTemplate.processElementUITemplate("rate", editConditionMap);
            } else if ("association".equals(projectTableFiledConfig.getShowType())) {
                String associationTable = projectTableFiledConfig.getAssociationTable();
                if (StringUtils.isBlank(associationTable)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为关联字段，但未配置关联表信息！");
                }
                JSONObject jsonObject = new JSONObject(associationTable);
                String table = jsonObject.getStr("table");
                String associationField = jsonObject.getStr("associationField");
                table = StrUtil.toCamelCase(table);
                associationField = StrUtil.toCamelCase(associationField);
                String showField = jsonObject.getStr("showField");
                if (StringUtils.isNotBlank(showField)) {
                    showField = StrUtil.toCamelCase(showField);
                    editConditionMap.put("vif", "${entityName!\"\"}." + table + " && ${entityName!\"\"}." + table + "." + showField);
                    editConditionMap.put("style", "color: grey");
                    editConditionMap.put("content", "已选择: {{${entityName!\"\"}." + table + "." + showField + "}}");
                    contentStr = ProcessFreemarkerTemplate.processElementUITemplate("span", editConditionMap);

                    editConditionMap.remove("vif");
                    editConditionMap.put("style", "margin-left: 10px");
                    editConditionMap.put("label", "选择" + label);
                    editConditionMap.put("click", "showComponent(false,'" + fieldName.getJavaName() + "','" + table + "','" + associationField + "','" + showField + "')");
                    contentStr += ProcessFreemarkerTemplate.processElementUITemplate("button", editConditionMap);
                }
            } else if ("collection".equals(projectTableFiledConfig.getShowType())) {
                throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为一对多字段，不应出现在编辑界面！");
            }
        }
        editFormStr.append(generationFormItem(label, contentStr, fieldName.getJavaName()));
        updateFieldMap.put(fieldName.getName(), editFormStr.toString());
    }

    /**
     * 生成新增框的代码
     *
     * @param addFieldMap
     * @param fieldName
     * @param projectTableFiledConfig
     * @throws IOException
     * @throws TemplateException
     */
    private static void generationAddForm(Map<String, String> addFieldMap, FieldName fieldName,
                                          ProjectTableFiledConfig projectTableFiledConfig) throws IOException, TemplateException {
        if (fieldName.isAutIncrement()) {
            //自增的字段就不需要手动填写了
            return;
        }
        StringBuilder addFormStr = new StringBuilder();
        Map<String, Object> addConditionMap = new HashMap<>();

        addConditionMap.put("vmodel", "${entityName!\"\"}." + fieldName.getJavaName());
        if (fieldName.isNotNull()) {
            addConditionMap.put("clearable", "false");
        }
        if (fieldName.getMaxLength() > 0) {
            addConditionMap.put("maxlength", fieldName.getMaxLength());
            addConditionMap.put("showWordLimit", "true");
        }
        if (fieldName.isNotNull()) {
            addConditionMap.put("prop", fieldName.getJavaName());
        }
        String contentStr = "";
        String label;
        if (projectTableFiledConfig == null) {
            label = Common.getStringNotNull(fieldName.getDesc(), fieldName.getJavaName());
            addConditionMap.put("label", label);
            contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                    "input", addConditionMap);
        } else {
            label = Common.getStringNotNull(projectTableFiledConfig.getShowName(), fieldName.getDesc());
            addConditionMap.put("label", label);

            if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                addConditionMap.put("prop", fieldName.getJavaName() + "Arr");
            }
//            类型: text, textarea, number, radio, checkbox, date,dateTime, file, img
            if ("text".equals(projectTableFiledConfig.getShowType())) {//文本框
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "input", addConditionMap);
            } else if ("textarea".equals(projectTableFiledConfig.getShowType())) {//文本框
                addConditionMap.put("type", "textarea");
                addConditionMap.put("autosize", "true");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "input", addConditionMap);
            } else if ("number".equals(projectTableFiledConfig.getShowType())) {
                addConditionMap.put("type", "number");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "input", addConditionMap);
            } else if ("date".equals(projectTableFiledConfig.getShowType())) {
                addConditionMap.put("style", "width: 100%;");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "datePicker", addConditionMap);
            } else if ("dateTime".equals(projectTableFiledConfig.getShowType())) {
                addConditionMap.put("style", "width: 100%;");
                addConditionMap.put("placeholder", "选择日期时间");
                addConditionMap.put("type", "datetime");
                addConditionMap.put("valueFormat", "yyyy-MM-dd HH:mm:ss");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate(
                        "datePicker", addConditionMap);
            } else if ("rate".equals(projectTableFiledConfig.getShowType())) {
                addConditionMap.put("showScore", "true");
                contentStr += ProcessFreemarkerTemplate.processElementUITemplate("rate", addConditionMap);
            } else if ("radio".equals(projectTableFiledConfig.getShowType())) {//单选
                String showSelectOption = projectTableFiledConfig.getShowSelectOption();
                if (StringUtils.isBlank(showSelectOption)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为单选框，但未配置选项值！");
                }
                JSONObject jsonObject = new JSONObject(showSelectOption);
                addConditionMap.put("optionData", jsonObject);
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate("select", addConditionMap);
            } else if ("checkbox".equals(projectTableFiledConfig.getShowType())) {
                String showSelectOption = projectTableFiledConfig.getShowSelectOption();
                if (StringUtils.isBlank(showSelectOption)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置多选框，但未配置选项值！");
                }
                JSONObject jsonObject = new JSONObject(showSelectOption);
                addConditionMap.put("optionData", jsonObject);
                addConditionMap.put("multiple", "true");
                addConditionMap.put("vmodel", "${entityName!\"\"}." + fieldName.getJavaName() + "Arr");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate("select", addConditionMap);
            } else if ("img".equals(projectTableFiledConfig.getShowType())) {
                addConditionMap.put("accept", "'.png, .jpg, .jpeg'");
                addConditionMap.put("listType", "picture");
                addConditionMap.put("fileList", "${entityName!\"\"}." + fieldName.getJavaName() + "?[{url:(baseUri + downloadPersonalFileUrl+${entityName!\"\"}." + fieldName.getJavaName() + ")}]:[]");
                addConditionMap.put("onRemove", "()=>handleRemoveImage('" + fieldName.getJavaName() + "')");
                addConditionMap.put("onExceed", "handleImageExceed");
                addConditionMap.put("beforeUpload", "beforeImageUpload");
                addConditionMap.put("httpRequest", "(file)=>handleImageUpload(file,'" + fieldName.getJavaName() + "')");
                addConditionMap.put("uploadTip", "只能上传jpg/png/jpeg文件，且不超过2MB");
                contentStr = ProcessFreemarkerTemplate.processElementUITemplate("upload", addConditionMap);
            } else if ("association".equals(projectTableFiledConfig.getShowType())) {
                String associationTable = projectTableFiledConfig.getAssociationTable();
                if (StringUtils.isBlank(associationTable)) {
                    throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为关联字段，但未配置关联表信息！");
                }
                JSONObject jsonObject = new JSONObject(associationTable);
                String table = jsonObject.getStr("table");
                String associationField = jsonObject.getStr("associationField");
                table = StrUtil.toCamelCase(table);
                associationField = StrUtil.toCamelCase(associationField);
                String showField = jsonObject.getStr("showField");
                if (StringUtils.isNotBlank(showField)) {
                    showField = StrUtil.toCamelCase(showField);
                    addConditionMap.put("vif", "${entityName!\"\"}." + table + " && ${entityName!\"\"}." + table + "." + showField);
                    addConditionMap.put("style", "color: grey");
                    addConditionMap.put("content", "已选择: {{${entityName!\"\"}." + table + "." + showField + "}}");
                    contentStr = ProcessFreemarkerTemplate.processElementUITemplate("span", addConditionMap);

                    addConditionMap.remove("vif");
                    addConditionMap.put("style", "margin-left: 10px");
                    addConditionMap.put("label", "选择" + label);
                    addConditionMap.put("click", "showComponent(false,'" + fieldName.getJavaName() + "','" + table + "','" + associationField + "','" + showField + "')");
                    contentStr += ProcessFreemarkerTemplate.processElementUITemplate("button", addConditionMap);
                }
            } else if ("collection".equals(projectTableFiledConfig.getShowType())) {
                throw new RuntimeException("表：" + projectTableFiledConfig.getTableName() + " 字段：" + projectTableFiledConfig.getFiledName() + " 配置为一对多字段，不应出现在新增界面！");
            }
        }
        addFormStr.append(generationFormItem(label, contentStr, fieldName.getJavaName()));
        addFieldMap.put(fieldName.getName(), addFormStr.toString());
    }

    /**
     * 处理formItem的代码
     *
     * @param label
     * @param showInExpandStr
     * @return
     * @throws IOException
     * @throws TemplateException
     */
    private static String generationFormItem(String label, String showInExpandStr, String propName) throws IOException, TemplateException {
        Map<String, String> map = new HashMap<>(2);
        map.put("content", showInExpandStr);
        map.put("label", label);
        map.put("prop", propName);
        return "              " + ProcessFreemarkerTemplate.processElementUITemplate("formItem", map);
    }
}
